lib/gpg: Show information for expired keys
authorDan Nicholson <nicholson@endlessm.com>
Mon, 10 Jun 2019 17:05:21 +0000 (12:05 -0500)
committerAtomic Bot <atomic-devel@projectatomic.io>
Wed, 19 Jun 2019 17:17:11 +0000 (17:17 +0000)
Introduce a new signature attribute for the key expiration timestamp and
display it when the key has a non-zero expiration time. Without this,
the error shown is `BAD signature`, which isn't correct.

Closes: #1872
Approved by: cgwalters

src/libostree/ostree-gpg-verify-result.c
src/libostree/ostree-gpg-verify-result.h
tests/test-gpg-verify-result.c

index a2fb86205939b746b3ea8df4628b27f2c65cf574..5a8888e76a438c253e6accc1169cce489b49fbb1 100644 (file)
@@ -65,7 +65,9 @@ static OstreeGpgSignatureAttr all_signature_attrs[] = {
   OSTREE_GPG_SIGNATURE_ATTR_HASH_ALGO_NAME,
   OSTREE_GPG_SIGNATURE_ATTR_USER_NAME,
   OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL,
-  OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY
+  OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY,
+  OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP,
+  OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY,
 };
 
 static void ostree_gpg_verify_result_initable_iface_init (GInitableIface *iface);
@@ -331,7 +333,9 @@ ostree_gpg_verify_result_get (OstreeGpgVerifyResult *result,
     {
       if (attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_USER_NAME ||
           attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL ||
-          attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY)
+          attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY ||
+          attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP ||
+          attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY)
         {
           (void) gpgme_get_key (result->context, signature->fpr, &key, 0);
           break;
@@ -345,6 +349,7 @@ ostree_gpg_verify_result_get (OstreeGpgVerifyResult *result,
       GVariant *child;
       gboolean v_boolean;
       const char *v_string = NULL;
+      gint64 v_int64;
 
       switch (attrs[ii])
         {
@@ -423,6 +428,29 @@ ostree_gpg_verify_result_get (OstreeGpgVerifyResult *result,
             child = g_variant_new_string (v_string);
             break;
 
+          case OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP:
+            v_int64 = 0;
+            if (key != NULL)
+              {
+                gpgme_subkey_t subkey = key->subkeys;
+
+                while (subkey != NULL && (g_strcmp0 (subkey->fpr, signature->fpr) != 0))
+                  subkey = subkey->next;
+
+                if (subkey != NULL)
+                  v_int64 = subkey->expires;
+              }
+            child = g_variant_new_int64 (v_int64);
+            break;
+
+          case OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY:
+            if (key != NULL && key->subkeys != NULL)
+              v_int64 = key->subkeys->expires;
+            else
+              v_int64 = 0;
+            child = g_variant_new_int64 (v_int64);
+            break;
+
           default:
             g_critical ("Invalid signature attribute (%d)", attrs[ii]);
             g_variant_builder_clear (&builder);
@@ -581,6 +609,8 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
   g_autofree char *formatted_date_time = NULL;
   gint64 timestamp;
   gint64 exp_timestamp;
+  gint64 key_exp_timestamp;
+  gint64 key_exp_timestamp_primary;
   const char *type_string;
   const char *fingerprint;
   const char *fingerprint_primary;
@@ -590,6 +620,7 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
   const char *key_id;
   gboolean valid;
   gboolean sig_expired;
+  gboolean key_expired;
   gboolean key_missing;
   gsize len;
 
@@ -599,7 +630,7 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
   /* Verify the variant's type string.  This code is
    * not prepared to handle just any random GVariant. */
   type_string = g_variant_get_type_string (variant);
-  g_return_if_fail (strcmp (type_string, "(bbbbbsxxsssss)") == 0);
+  g_return_if_fail (strcmp (type_string, "(bbbbbsxxsssssxx)") == 0);
 
   /* The default format roughly mimics the verify output generated by
    * check_sig_and_print() in gnupg/g10/mainproc.c, though obviously
@@ -609,6 +640,8 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
                        "b", &valid);
   g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_SIG_EXPIRED,
                        "b", &sig_expired);
+  g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_EXPIRED,
+                       "b", &key_expired);
   g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_MISSING,
                        "b", &key_missing);
   g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT,
@@ -625,6 +658,10 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
                        "&s", &user_name);
   g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL,
                        "&s", &user_email);
+  g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP,
+                       "x", &key_exp_timestamp);
+  g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY,
+                       "x", &key_exp_timestamp_primary);
 
   len = strlen (fingerprint);
   key_id = (len > 16) ? fingerprint + len - 16 : fingerprint;
@@ -697,6 +734,12 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
   if (exp_timestamp > 0)
     append_expire_info (output_buffer, line_prefix, "Signature", exp_timestamp,
                         sig_expired);
+  if (key_exp_timestamp > 0)
+    append_expire_info (output_buffer, line_prefix, "Key", key_exp_timestamp,
+                        key_expired);
+  if (key_exp_timestamp_primary > 0 && (g_strcmp0 (fingerprint, fingerprint_primary) != 0))
+    append_expire_info (output_buffer, line_prefix, "Primary key",
+                        key_exp_timestamp_primary, key_expired);
 }
 
 /**
index 0a77ec533dbd908013909973338d29ec70e2e47f..7c71ecdca92c833e94339b4fe8d298789cfa9f27 100644 (file)
@@ -70,6 +70,14 @@ typedef struct OstreeGpgVerifyResult OstreeGpgVerifyResult;
  *   (will be the same as OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT if the
  *   the signature is already from the primary key rather than a subkey,
  *   and will be the empty string if the key is missing.)
+ * @OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP:
+ *   [#G_VARIANT_TYPE_INT64] Key expiration Unix timestamp (0 if no
+ *   expiration or if the key is missing)
+ * @OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY:
+ *   [#G_VARIANT_TYPE_INT64] Key expiration Unix timestamp of the signing key's
+ *   primary key (will be the same as OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP
+ *   if the signing key is the primary key and 0 if no expiration or if the key
+ *   is missing)
  *
  * Signature attributes available from an #OstreeGpgVerifyResult.
  * The attribute's #GVariantType is shown in brackets.
@@ -88,6 +96,8 @@ typedef enum {
   OSTREE_GPG_SIGNATURE_ATTR_USER_NAME,
   OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL,
   OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY,
+  OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP,
+  OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY,
 } OstreeGpgSignatureAttr;
 
 _OSTREE_PUBLIC
index 19d6f71ed5b01a4db97a4e64e3cd2cd3ace9b698..95de1873a2026883b0a6446d1d06d41783138bd2 100644 (file)
@@ -45,7 +45,8 @@ static OstreeGpgSignatureAttr some_attributes[] = {
   OSTREE_GPG_SIGNATURE_ATTR_SIG_EXPIRED,
   OSTREE_GPG_SIGNATURE_ATTR_KEY_EXPIRED,
   OSTREE_GPG_SIGNATURE_ATTR_KEY_REVOKED,
-  OSTREE_GPG_SIGNATURE_ATTR_KEY_MISSING
+  OSTREE_GPG_SIGNATURE_ATTR_KEY_MISSING,
+  OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP,
 };
 
 static void
@@ -174,7 +175,7 @@ test_attribute_basics (TestFixture *fixture,
       tuple = ostree_gpg_verify_result_get_all (fixture->result, ii);
 
       type_string = g_variant_get_type_string (tuple);
-      g_assert_cmpstr (type_string, ==, "(bbbbbsxxsssss)");
+      g_assert_cmpstr (type_string, ==, "(bbbbbsxxsssssxx)");
 
       /* Check attributes which should be common to all signatures. */
 
@@ -221,24 +222,27 @@ test_valid_signature (TestFixture *fixture,
   gboolean key_expired;
   gboolean key_revoked;
   gboolean key_missing;
+  gint64 key_exp_timestamp;
 
   tuple = ostree_gpg_verify_result_get (fixture->result,
                                         signature_index,
                                         some_attributes,
                                         G_N_ELEMENTS (some_attributes));
 
-  g_variant_get (tuple, "(bbbbb)",
+  g_variant_get (tuple, "(bbbbbx)",
                  &valid,
                  &sig_expired,
                  &key_expired,
                  &key_revoked,
-                 &key_missing);
+                 &key_missing,
+                 &key_exp_timestamp);
 
   g_assert_true (valid);
   g_assert_false (sig_expired);
   g_assert_false (key_expired);
   g_assert_false (key_revoked);
   g_assert_false (key_missing);
+  g_assert_cmpint (key_exp_timestamp, ==, 0);
 }
 
 static void
@@ -252,24 +256,27 @@ test_expired_key (TestFixture *fixture,
   gboolean key_expired;
   gboolean key_revoked;
   gboolean key_missing;
+  gint64 key_exp_timestamp;
 
   tuple = ostree_gpg_verify_result_get (fixture->result,
                                         signature_index,
                                         some_attributes,
                                         G_N_ELEMENTS (some_attributes));
 
-  g_variant_get (tuple, "(bbbbb)",
+  g_variant_get (tuple, "(bbbbbx)",
                  &valid,
                  &sig_expired,
                  &key_expired,
                  &key_revoked,
-                 &key_missing);
+                 &key_missing,
+                 &key_exp_timestamp);
 
   g_assert_false (valid);
   g_assert_false (sig_expired);
   g_assert_true (key_expired);
   g_assert_false (key_revoked);
   g_assert_false (key_missing);
+  g_assert_cmpint (key_exp_timestamp, ==, 1426782201);
 }
 
 static void
@@ -283,24 +290,27 @@ test_revoked_key (TestFixture *fixture,
   gboolean key_expired;
   gboolean key_revoked;
   gboolean key_missing;
+  gint64 key_exp_timestamp;
 
   tuple = ostree_gpg_verify_result_get (fixture->result,
                                         signature_index,
                                         some_attributes,
                                         G_N_ELEMENTS (some_attributes));
 
-  g_variant_get (tuple, "(bbbbb)",
+  g_variant_get (tuple, "(bbbbbx)",
                  &valid,
                  &sig_expired,
                  &key_expired,
                  &key_revoked,
-                 &key_missing);
+                 &key_missing,
+                 &key_exp_timestamp);
 
   g_assert_false (valid);
   g_assert_false (sig_expired);
   g_assert_false (key_expired);
   g_assert_true (key_revoked);
   g_assert_false (key_missing);
+  g_assert_cmpint (key_exp_timestamp, ==, 0);
 }
 
 static void
@@ -314,24 +324,27 @@ test_missing_key (TestFixture *fixture,
   gboolean key_expired;
   gboolean key_revoked;
   gboolean key_missing;
+  gint64 key_exp_timestamp;
 
   tuple = ostree_gpg_verify_result_get (fixture->result,
                                         signature_index,
                                         some_attributes,
                                         G_N_ELEMENTS (some_attributes));
 
-  g_variant_get (tuple, "(bbbbb)",
+  g_variant_get (tuple, "(bbbbbx)",
                  &valid,
                  &sig_expired,
                  &key_expired,
                  &key_revoked,
-                 &key_missing);
+                 &key_missing,
+                 &key_exp_timestamp);
 
   g_assert_false (valid);
   g_assert_false (sig_expired);
   g_assert_false (key_expired);
   g_assert_false (key_revoked);
   g_assert_true (key_missing);
+  g_assert_cmpint (key_exp_timestamp, ==, 0);
 }
 
 static void
@@ -345,24 +358,27 @@ test_expired_signature (TestFixture *fixture,
   gboolean key_expired;
   gboolean key_revoked;
   gboolean key_missing;
+  gint64 key_exp_timestamp;
 
   tuple = ostree_gpg_verify_result_get (fixture->result,
                                         signature_index,
                                         some_attributes,
                                         G_N_ELEMENTS (some_attributes));
 
-  g_variant_get (tuple, "(bbbbb)",
+  g_variant_get (tuple, "(bbbbbx)",
                  &valid,
                  &sig_expired,
                  &key_expired,
                  &key_revoked,
-                 &key_missing);
+                 &key_missing,
+                 &key_exp_timestamp);
 
   g_assert_true (valid);
   g_assert_true (sig_expired);
   g_assert_false (key_expired);
   g_assert_false (key_revoked);
   g_assert_false (key_missing);
+  g_assert_cmpint (key_exp_timestamp, ==, 0);
 }
 
 int